﻿using System;
using System.Reflection;

#if NET4
using TypeInfo = System.Type;
#endif

namespace Beaker.Reflection
{
	/// <summary>
	/// Extenion methods on <see cref="TypeInfo"/> and <see cref="Type"/>.
	/// </summary>
	public static class TypeInfoExtensions
	{
		/// <summary>
		/// Gets if the provided type info is a <see cref="Maybe{T}"/>.
		/// </summary>
		/// <param name="typeInfo">The type info to check if it is a <see cref="Maybe{T}"/>.</param>
		/// <returns><c>true</c> if the type is a <see cref="Maybe{T}"/>; otherwise <c>false</c>.</returns>
		public static bool IsMaybe(this TypeInfo typeInfo)
		{
			return typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == typeof(Maybe<>);
		}

		/// <summary>
		/// Gets if the provided type info is a <see cref="Nullable{T}"/>.
		/// </summary>
		/// <param name="typeInfo">The type info to check if it is a <see cref="Nullable{T}"/>.</param>
		/// <returns><c>true</c> if the type is a <see cref="Nullable{T}"/>; otherwise <c>false</c>.</returns>
		public static bool IsNullable(this TypeInfo typeInfo)
		{
			return typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == typeof(Nullable<>);
		}

		/// <summary>
		/// Gets the underlying type 
		/// </summary>
		/// <param name="type">The type (Enum, Maybe or Nullable) to get the underlying type for.</param>
		/// <returns>The underyling type</returns>
		/// <exception cref="NotSupportedException">The provided type does not support to get the underlying type for.</exception>
		public static Type GetUnderlyingType(this Type type)
		{
			TypeInfo typeInfo = type.GetTypeInfo();
			if (typeInfo.IsArray)
				return typeInfo.GetElementType();
			if (typeInfo.IsEnum)
				return Enum.GetUnderlyingType(type);
			if (typeInfo.IsMaybe())
				return Maybe.GetUnderlyingType(type);
			if (typeInfo.IsNullable())
				return Nullable.GetUnderlyingType(type);

			throw new NotSupportedException("GetUnderlyingType is only supported on Enum, Maybe and Nullable");
		}

	}
}